package com.woniu.sso_jwt.jwtutils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.woniu.sso_jwt.jwtresult.JWTResult;
import io.jsonwebtoken.*;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.util.Date;

public class JWTUtil {
    //服务器的key,用于做加解密的key数据，如果可以使用客户端生成的key，此处可以补定义
private  static final String JWT_SECERT_KEY="test_jwt_secert";
//用于Jackson的Java对象和字符串的转换
private static final ObjectMapper MAPPER=new ObjectMapper();
private static final int  JWT_ERRCODE_EXPRIE=1005; //token过期的表示符
private  static final int JWT_ERRCODE_FAIL=1006; //验证不通过的表示符

    //获取加密的key
    public static SecretKey generalKey(){
        try {
            byte[] encodeKey=JWT_SECERT_KEY.getBytes("UTF-8");
            //最基础的密匙创建，ase加密方式
            SecretKey key=new SecretKeySpec(encodeKey,0,encodeKey.length,"ASE");
            return key;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 签发JWT，创建token方法
     * id,jwt的唯一的身份标识，主要用来作为一次性token,从而回避重放攻击
     * iss,jwt签发者,数去生成的信息
     * subject ,jwt所面向的用户，paylaod中记录的public claims,当前环境就是用户名，自定义的
     * ttlmillis,有效期，单位毫秒
     * return toekn
     */

    public  static String createJWTToken(String id,String iss,String subject ,long ttlMillis){
     //创建一个生成的加密算法
        SignatureAlgorithm signatureAlgorithm=SignatureAlgorithm.HS256;
      //当前时间
        long nowMillis=System.currentTimeMillis();
        //当前时间的日期对象
        Date now=new Date(nowMillis);
       //密匙对象生成出来
        SecretKey secretKey =generalKey();
        //创建jwt 的构建器，使用指定的信息和加密算法生成token的工具
        JwtBuilder builder= Jwts.builder()
                .setId(id)//设置身份标志,一个客户端的唯一标记
                .setIssuer(iss)
                .setSubject(subject)//payload的公开信息
                .setIssuedAt(now)//toekn生成的时间
                .signWith(signatureAlgorithm,secretKey);//设定算法，密匙
        if(ttlMillis>=0){
            long expMillis=nowMillis+ttlMillis;
            Date expDate=new Date(expMillis);//设置失效时间
            builder.setExpiration(expDate);
        }
        //生成token
        return builder.compact();
    }



    /*验证toekn*/
public static JWTResult validateJWT(String jwtstr){
        JWTResult jwtResult=new JWTResult();
    Claims claims=null;
try {
    claims=parseJWT(jwtstr);
    jwtResult.setSuccess(true);
    jwtResult.setClaims(claims);
}catch (ExpiredJwtException e){
    //超时
    jwtResult.setErrCode(JWT_ERRCODE_EXPRIE);
    jwtResult.setSuccess(false);
}catch (SignatureException e){
    //校验失败
    jwtResult.setErrCode(JWT_ERRCODE_FAIL);
    jwtResult.setSuccess(false);
}catch (Exception e){
jwtResult.setErrCode(JWT_ERRCODE_FAIL);
jwtResult.setSuccess(false);
}
return  jwtResult;
    }

    /*
    * 解析jwt字符串
    * jwt就是服务器为客户生成的签名数据，就是token
    *
    * */
    private static Claims parseJWT(String jwtstr) {
        SecretKey secretKey=generalKey();
        return (Claims) Jwts.parser()
                .setSigningKey(secretKey)
                .parse(jwtstr)
                .getBody();
        //获取的就是token中记录的payload数据，就是payload中保存的所有的claims
    }

    /*
    * 生成subject信息
    * subobj，要转换的对象
    *
    * Java对象————》json字符串出错时返回null
    * */
public static String  generalSubject(Object subobj){
    try {
        return MAPPER.writeValueAsString(subobj);
    } catch (JsonProcessingException e) {
        e.printStackTrace();
        return null;
    }

}

}
